#include "cbb_event.h"
#include <stdint.h>
#include <stddef.h>
#include "cbb_bit.h"

// 事件链表头
Event_t* pstHead = NULL;

Event_t*
cbb_event_register(void* pu32Event, Event_Type_t eType, uint32_t u32BitMap){

    // 输入参数检查
    if(NULL == pu32Event) return NULL;

    // 申请内存
    Event_t* pstEvent = (Event_t*)EVENT_MALLOC(sizeof(Event_t));
    if(NULL == pstEvent) return NULL;

    // 初始化事件
    pstEvent->pu32Event = pu32Event;
    pstEvent->eType = eType;
    pstEvent->u32BitMap = u32BitMap;
    pstEvent->pstEventCB = NULL;
    pstEvent->pstNext = NULL;

    // 加入链表 -- 尾插法
    if(NULL == pstHead) pstHead = pstEvent;
    else{
        pstEvent->pstNext = pstHead;
        pstHead = pstEvent;
    }
    
    // 返回事件
    return pstEvent;
}

EVENT_RET_t 
cbb_event_connect(Event_t* pstEvent, Event_CB_t pfnCallback, void* pvArgs){
    
    // 输入参数检查
    if(NULL == pstEvent || NULL == pfnCallback) return EVENT_ERR;

    // 申请内存
    Event_Callback_t* pstEventCB = (Event_Callback_t*)EVENT_MALLOC(sizeof(Event_Callback_t));
    if(NULL == pstEventCB) return EVENT_ERR;

    // 初始化回调函数
    pstEventCB->pfnCallback = pfnCallback;
    pstEventCB->pvArgs = pvArgs;
    pstEventCB->pstNext = NULL;

    // 加入链表 -- 尾插法
    if(NULL == pstEvent->pstEventCB) pstEvent->pstEventCB = pstEventCB;
    else{
        pstEventCB->pstNext = pstEvent->pstEventCB;
        pstEvent->pstEventCB = pstEventCB;
    }

    // 返回成功
    return EVENT_OK;
}

void
cbb_event_monitor(Event_t* pstEvent){

    // 输入参数检查
    if(NULL == pstEvent) return;

    // 获取事件位
    uint8_t u8Ret = cbb_get_bit(pstEvent->pu32Event, pstEvent->eType ,pstEvent->u32BitMap);
    if(0 == u8Ret) return;

    // 遍历事件回调链表
    Event_Callback_t* pstEventCB = pstEvent->pstEventCB;
    while(NULL != pstEventCB){

        // 事件发生
        if(pstEventCB->pfnCallback) pstEventCB->pfnCallback(pstEventCB->pvArgs);
        
        // 遍历下一个回调函数
        pstEventCB = pstEventCB->pstNext;
    }

    // 清除事件位
    cbb_clear_bit(pstEvent->pu32Event, pstEvent->eType, pstEvent->u32BitMap);
}

void
cbb_event_run(void){
    
    // 遍历事件链表
    Event_t* pstEvent = pstHead;
    while(NULL != pstEvent){

        // 遍历事件回调链表
        cbb_event_monitor(pstEvent);

        // 遍历下一个事件
        pstEvent = pstEvent->pstNext;
    }
}
